package org.jeecg.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ClassUtils;

import java.io.*;

/**
 * 复制resource文件、文件夹
 */
@Slf4j
public class FileForJarUtil {

    /**
     * 复制path目录下所有文件，覆盖（jar）
     *
     * @param path    文件目录 不能以/开头
     * @param newPath 新文件目录
     */
    public static void copyFolderFromJarCover(String prefix, String path, String newPath) throws IOException {
        log.info("准备拷贝jar中的文件，Prefix={}, {}-->>{}", prefix, path, newPath);
        if (!new File(newPath).exists()) {
            new File(newPath).mkdir();
        }

        path = path.replace("\\", "/");
        if (path.startsWith("/")) {
            //以/开头，去掉/
            path = path.substring(1);
        }
        if (path.endsWith("/")) {
            //以/结尾，去掉/
            path = path.substring(0, path.length() - 1);
        }

        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        //获取所有匹配的文件（包含根目录文件、子目录、子目录下的文件）
        Resource[] resources = resolver.getResources("classpath:" + path + "/**/");
        if(resources == null){
            return;
        }
        //打印有多少文件
        for (Resource resource : resources) {
            //以jar包运行时，不能使用resource.getFile()获取文件路径、判断是否为文件等，会报错：
            //java.io.FileNotFoundException: class path resource [xxx/xxx/] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxx.jar!/BOOT-INF/classes!/xxx/xxx

            //文件路径
            //file [/xxx/xxx]
            String description = resource.getDescription();
            description = description.replace("\\", "/");
            //保留 /xxx/xxx
            description = description.replaceAll("(.*\\[)|(]$)", "").trim();

            //以“文件目录”进行分割，获取文件相对路径
            String[] descriptions = description.split(path + "/");
            if (descriptions.length > 1) {
                //获取文件相对路径，/xxx/xxx
                String relativePath = descriptions[1];
                if (!(relativePath + "/").startsWith(prefix)) {
                    continue;
                }

                //新文件路径
                String newFilePath = newPath + "/" + relativePath;
                if (isDirectory(relativePath)) {
                    //文件夹
                    File newFile = new File(newFilePath);
                    if (!newFile.exists()) {
                        newFile.mkdir();
                    }
                } else {
                    //文件
                    try(InputStream stream = resource.getInputStream();){
                        write2File(stream, newFilePath);
                    }
                }
            }
        }
        log.info("拷贝jar中的文件完成，Prefix={}, {}-->>{}", prefix, path, newPath);
    }

    /**
     * 复制文件（jar）
     *
     * @param path    源文件路径
     * @param newPath 新文件路径
     */
    public static void copyFileFromJar(String path, String newPath) throws IOException {
        //不读文件路径，直接读取文件流
        InputStream inputStream = ClassUtils.getDefaultClassLoader().getResourceAsStream(path);
        write2File(inputStream, newPath);
    }

    /**
     * 输入流写入文件
     *
     * @param is       输入流
     * @param filePath 文件保存目录路径
     * @throws IOException IOException
     */
    public static void write2File(InputStream is, String filePath) throws IOException {
        File destFile = new File(filePath);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }

        if (!destFile.exists()) {
            destFile.createNewFile();
        }

        try(OutputStream os = new FileOutputStream(destFile);){
            int len = 8192;
            byte[] buffer = new byte[len];
            while ((len = is.read(buffer, 0, len)) != -1) {
                os.write(buffer, 0, len);
            }
        }
    }

    /**
     * 判断是否为目录、文件夹
     * @param filename 文件名
     * @return boolean
     */
    public static boolean isDirectory(String filename) {
        if (StringUtils.isBlank(filename)) {
            return false;
        }

        //有后缀，是文件
        boolean contains = filename.contains(".");
        if (contains) {
            return false;
        }

        //是文件夹
        return true;
    }

}